package fudan.se.lab2.service;

import fudan.se.lab2.controller.request.ReviewRequest;
import fudan.se.lab2.domain.*;
import fudan.se.lab2.repository.*;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;

import javax.servlet.ServletOutputStream;
import javax.servlet.http.HttpServletResponse;
import java.io.File;
import java.io.FileInputStream;
import java.io.IOException;
import java.util.ArrayList;
import java.util.List;

@Service
public class ReviewService {
    private final Logger logger = LoggerFactory.getLogger("ReviewService.class");
    private final MarkRepository markRepository;
    private final DistributionRepository distributionRepository;
    private final MeetingRepository meetingRepository;
    private final ContributionRepository contributionRepository;
    private final PostRepository postRepository;

    @Autowired
    public ReviewService(MarkRepository markRepository, DistributionRepository distributionRepository, MeetingRepository meetingRepository, ContributionRepository contributionRepository, PostRepository postRepository) {
        this.markRepository = markRepository;
        this.distributionRepository = distributionRepository;
        this.meetingRepository = meetingRepository;
        this.contributionRepository = contributionRepository;
        this.postRepository = postRepository;
    }


    public Mark review(ReviewRequest request) {
        Mark reviewMark = markRepository.findByContributorAndTitle(request.getContributor(), request.getTitle());
        Contribution contribution = contributionRepository.findByContributorAndMeetingFullNameAndFileTitle(request.getContributor(), request.getMeetingName(), request.getTitle());
        if (reviewMark == null) {
            List<String> pcMembers = new ArrayList<>();
            pcMembers.add(request.getPcMember());

            List<String> marks = new ArrayList<>();
            marks.add(request.getMark());
            List<String> comments = new ArrayList<>();
            comments.add(request.getComment());
            List<String> confidences = new ArrayList<>();
            confidences.add(request.getConfidence());
            reviewMark = new Mark(request.getContributor(), request.getTitle(), pcMembers, marks, comments, confidences);
            markRepository.save(reviewMark);
        } else {
            reviewMark.getPcMembers().add(request.getPcMember());
            reviewMark.getMarks().add(request.getMark());
            reviewMark.getComments().add(request.getComment());
            reviewMark.getConfidences().add(request.getConfidence());
            markRepository.save(reviewMark);
        }
        if (request.getMark().equals("-1") || request.getMark().equals("-2")) {
            reviewMark.setPassed(false);
            contribution.setStatus(-1);
        }
        Distribution distribution = distributionRepository.findByFileTitleAndMeetingFullNameAndUsername(request.getTitle(), request.getMeetingName(), request.getPcMember());
        distribution.setStatus(1);
        distributionRepository.save(distribution);
        if (reviewMark.getPcMembers().size() == 3) {
            openFirstPost(request.getMeetingName(), request.getTitle());
        }
        return reviewMark;
    }

    private void openFirstPost(String meetingFullName, String title) {
        Iterable<Distribution> distributions = distributionRepository.findByFileTitleAndMeetingFullName(title, meetingFullName);
        for (Distribution distribution : distributions) {
            if (distribution.getStatus() != 1)
                return;
        }
        Post post = new Post(title, meetingFullName, 1);
        postRepository.save(post);
    }

    public void download(String url, HttpServletResponse response) {
        String fileName = url.substring(url.lastIndexOf('/'));

        //1.设置文件ContentType类型，这样设置，会自动判断下载文件类型
        response.setContentType("multipart/form-data");
        //2.设置文件头：最后一个参数是设置下载文件名(假如我们叫a.pdf)
        response.setHeader("Content-Disposition", "attachment;fileName=" + fileName);
        //通过文件路径获得File对象
        File file = new File(url);
        try (FileInputStream inputStream = new FileInputStream(file);
             ServletOutputStream out = response.getOutputStream();
        ) {
            //3.通过response获取ServletOutputStream对象(out)
            int b = 0;
            byte[] buffer = new byte[512];
            while (b != -1) {
                b = inputStream.read(buffer);
                //4.写到输出流(out)中
                out.write(buffer, 0, b);
            }
        } catch (IOException e) {
            logger.debug("IOException: " + e.getMessage());
        }
    }

    private boolean isCommented(ReviewRequest request) {
        Meeting meeting = meetingRepository.findMeetingByFullName(request.getMeetingName());
        int postType = 0;
        if (meeting.getStatus() == 3) {
            postType = 1;
        } else if (meeting.getStatus() == 4) {
            postType = 2;
        }
        Post post = postRepository.findByMeetingFullNameAndTitleAndType(request.getMeetingName(), request.getTitle(), postType);
        List<String> pcs = post.getPcMembers();
        for (String pc : pcs) {
            if (pc.equals(request.getPcMember()))
                return true;
        }
        return false;
    }

    public boolean changeReview(ReviewRequest request) {
        if (!isCommented(request))
            return false;
        Mark reviewMark = markRepository.findByContributorAndTitle(request.getContributor(), request.getTitle());
        int i;
        List<String> pcMembers = reviewMark.getPcMembers();
        for (i = 0; i < pcMembers.size(); i++) {
            if (pcMembers.get(i).equals(request.getPcMember()))
                break;
        }
        reviewMark.getMarks().set(i, request.getMark());
        reviewMark.getComments().set(i, request.getComment());
        reviewMark.getConfidences().set(i, request.getConfidence());
        markRepository.save(reviewMark);
        int nextDistributionStatus = 0;
        Meeting meeting = meetingRepository.findMeetingByFullName(request.getMeetingName());
        Distribution distribution = distributionRepository.findByFileTitleAndMeetingFullNameAndUsername(request.getTitle(), request.getMeetingName(), request.getPcMember());
        if (meeting.getStatus() == 3) {
            nextDistributionStatus = 2;
        } else if (meeting.getStatus() == 4) {
            nextDistributionStatus = 3;
        }
        distribution.setStatus(nextDistributionStatus);
        distributionRepository.save(distribution);
        return true;
    }

    public boolean refuseToChangeReview(ReviewRequest request) {
        if (!isCommented(request))
            return false;
        int nextDistributionStatus = 0;
        Meeting meeting = meetingRepository.findMeetingByFullName(request.getMeetingName());
        Distribution distribution = distributionRepository.findByFileTitleAndMeetingFullNameAndUsername(request.getTitle(), request.getMeetingName(), request.getPcMember());
        if (meeting.getStatus() == 3) {
            nextDistributionStatus = 2;
        } else if (meeting.getStatus() == 4) {
            nextDistributionStatus = 3;
        }
        distribution.setStatus(nextDistributionStatus);
        distributionRepository.save(distribution);
        return true;
    }


}
